<template>
  <div id="app">
    <div class="game-container">
      <div class="header">
        <h1>2048</h1>
        <div class="score-container">
          <div class="score">
            <span class="score-label">分数</span>
            <span class="score-value">{{ score }}</span>
          </div>
          <div class="best-score">
            <span class="score-label">最高分</span>
            <span class="score-value">{{ bestScore }}</span>
          </div>
        </div>
        <button @click="newGame" class="new-game-btn">新游戏</button>
      </div>
      
      <div class="game-board" 
           @touchstart="handleTouchStart" 
           @touchmove="handleTouchMove" 
           @touchend="handleTouchEnd"
           @keydown="handleKeyDown"
           tabindex="0"
           ref="gameBoard">
        <div class="grid-container">
          <div class="grid-row" v-for="(row, rowIndex) in board" :key="rowIndex">
            <div class="grid-cell" 
                 v-for="(cell, colIndex) in row" 
                 :key="colIndex"
                 :class="getCellClass(cell)">
              <span v-if="cell !== 0" class="cell-value">{{ cell }}</span>
            </div>
          </div>
        </div>
      </div>
      
      <div class="game-over" v-if="gameOver">
        <div class="game-over-content">
          <h2>游戏结束!</h2>
          <p>最终分数: {{ score }}</p>
          <button @click="newGame" class="new-game-btn">再来一局</button>
        </div>
      </div>
      
      <div class="win" v-if="gameWon && !gameOver">
        <div class="win-content">
          <h2>恭喜你赢了!</h2>
          <p>分数: {{ score }}</p>
          <button @click="continueGame" class="continue-btn">继续游戏</button>
          <button @click="newGame" class="new-game-btn">新游戏</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      board: [],
      score: 0,
      bestScore: 0,
      gameOver: false,
      gameWon: false,
      touchStartX: 0,
      touchStartY: 0,
      touchEndX: 0,
      touchEndY: 0
    }
  },
  mounted() {
    this.initGame()
    this.loadBestScore()
    this.$refs.gameBoard.focus()
  },
  methods: {
    initGame() {
      this.board = this.createEmptyBoard()
      this.score = 0
      this.gameOver = false
      this.gameWon = false
      this.addRandomTile()
      this.addRandomTile()
    },
    
    createEmptyBoard() {
      return Array(4).fill().map(() => Array(4).fill(0))
    },
    
    addRandomTile() {
      const emptyCells = []
      for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
          if (this.board[i][j] === 0) {
            emptyCells.push({ row: i, col: j })
          }
        }
      }
      
      if (emptyCells.length > 0) {
        const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)]
        this.board[randomCell.row][randomCell.col] = Math.random() < 0.9 ? 2 : 4
      }
    },
    
    move(direction) {
      const oldBoard = JSON.stringify(this.board)
      let moved = false
      
      switch (direction) {
        case 'up':
          moved = this.moveUp()
          break
        case 'down':
          moved = this.moveDown()
          break
        case 'left':
          moved = this.moveLeft()
          break
        case 'right':
          moved = this.moveRight()
          break
      }
      
      if (moved) {
        this.addRandomTile()
        this.checkGameState()
        this.saveBestScore()
      }
    },
    
    moveLeft() {
      let moved = false
      for (let i = 0; i < 4; i++) {
        const row = this.board[i].filter(cell => cell !== 0)
        for (let j = 0; j < row.length - 1; j++) {
          if (row[j] === row[j + 1]) {
            row[j] *= 2
            this.score += row[j]
            row.splice(j + 1, 1)
            moved = true
          }
        }
        const newRow = row.concat(Array(4 - row.length).fill(0))
        if (JSON.stringify(this.board[i]) !== JSON.stringify(newRow)) {
          moved = true
        }
        this.board[i] = newRow
      }
      return moved
    },
    
    moveRight() {
      let moved = false
      for (let i = 0; i < 4; i++) {
        const row = this.board[i].filter(cell => cell !== 0)
        for (let j = row.length - 1; j > 0; j--) {
          if (row[j] === row[j - 1]) {
            row[j] *= 2
            this.score += row[j]
            row.splice(j - 1, 1)
            moved = true
          }
        }
        const newRow = Array(4 - row.length).fill(0).concat(row)
        if (JSON.stringify(this.board[i]) !== JSON.stringify(newRow)) {
          moved = true
        }
        this.board[i] = newRow
      }
      return moved
    },
    
    moveUp() {
      let moved = false
      for (let j = 0; j < 4; j++) {
        const col = []
        for (let i = 0; i < 4; i++) {
          if (this.board[i][j] !== 0) {
            col.push(this.board[i][j])
          }
        }
        for (let i = 0; i < col.length - 1; i++) {
          if (col[i] === col[i + 1]) {
            col[i] *= 2
            this.score += col[i]
            col.splice(i + 1, 1)
            moved = true
          }
        }
        const newCol = col.concat(Array(4 - col.length).fill(0))
        for (let i = 0; i < 4; i++) {
          if (this.board[i][j] !== newCol[i]) {
            moved = true
          }
          this.board[i][j] = newCol[i]
        }
      }
      return moved
    },
    
    moveDown() {
      let moved = false
      for (let j = 0; j < 4; j++) {
        const col = []
        for (let i = 0; i < 4; i++) {
          if (this.board[i][j] !== 0) {
            col.push(this.board[i][j])
          }
        }
        for (let i = col.length - 1; i > 0; i--) {
          if (col[i] === col[i - 1]) {
            col[i] *= 2
            this.score += col[i]
            col.splice(i - 1, 1)
            moved = true
          }
        }
        const newCol = Array(4 - col.length).fill(0).concat(col)
        for (let i = 0; i < 4; i++) {
          if (this.board[i][j] !== newCol[i]) {
            moved = true
          }
          this.board[i][j] = newCol[i]
        }
      }
      return moved
    },
    
    checkGameState() {
      // 检查是否赢了
      for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
          if (this.board[i][j] === 2048) {
            this.gameWon = true
          }
        }
      }
      
      // 检查是否游戏结束
      if (this.isGameOver()) {
        this.gameOver = true
      }
    },
    
    isGameOver() {
      // 检查是否有空格
      for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
          if (this.board[i][j] === 0) {
            return false
          }
        }
      }
      
      // 检查是否可以合并
      for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
          const current = this.board[i][j]
          if (j < 3 && this.board[i][j + 1] === current) return false
          if (i < 3 && this.board[i + 1][j] === current) return false
        }
      }
      
      return true
    },
    
    newGame() {
      this.initGame()
    },
    
    continueGame() {
      this.gameWon = false
    },
    
    handleKeyDown(event) {
      switch (event.key) {
        case 'ArrowUp':
          event.preventDefault()
          this.move('up')
          break
        case 'ArrowDown':
          event.preventDefault()
          this.move('down')
          break
        case 'ArrowLeft':
          event.preventDefault()
          this.move('left')
          break
        case 'ArrowRight':
          event.preventDefault()
          this.move('right')
          break
      }
    },
    
    handleTouchStart(event) {
      this.touchStartX = event.touches[0].clientX
      this.touchStartY = event.touches[0].clientY
    },
    
    handleTouchMove(event) {
      event.preventDefault()
    },
    
    handleTouchEnd(event) {
      this.touchEndX = event.changedTouches[0].clientX
      this.touchEndY = event.changedTouches[0].clientY
      
      const deltaX = this.touchEndX - this.touchStartX
      const deltaY = this.touchEndY - this.touchStartY
      
      if (Math.abs(deltaX) > Math.abs(deltaY)) {
        if (deltaX > 50) {
          this.move('right')
        } else if (deltaX < -50) {
          this.move('left')
        }
      } else {
        if (deltaY > 50) {
          this.move('down')
        } else if (deltaY < -50) {
          this.move('up')
        }
      }
    },
    
    getCellClass(value) {
      if (value === 0) return 'grid-cell empty'
      return `grid-cell tile-${value}`
    },
    
    loadBestScore() {
      const saved = localStorage.getItem('2048-best-score')
      if (saved) {
        this.bestScore = parseInt(saved)
      }
    },
    
    saveBestScore() {
      if (this.score > this.bestScore) {
        this.bestScore = this.score
        localStorage.setItem('2048-best-score', this.bestScore.toString())
      }
    }
  }
}
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: 'Arial', sans-serif;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

#app {
  width: 100%;
  max-width: 500px;
  padding: 20px;
}

.game-container {
  background: rgba(255, 255, 255, 0.95);
  border-radius: 20px;
  padding: 30px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}

.header {
  text-align: center;
  margin-bottom: 30px;
}

.header h1 {
  font-size: 48px;
  color: #776e65;
  margin-bottom: 20px;
  font-weight: bold;
}

.score-container {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-bottom: 20px;
}

.score, .best-score {
  background: #bbada0;
  padding: 15px 20px;
  border-radius: 10px;
  color: white;
  text-align: center;
  min-width: 100px;
}

.score-label {
  display: block;
  font-size: 14px;
  margin-bottom: 5px;
}

.score-value {
  display: block;
  font-size: 24px;
  font-weight: bold;
}

.new-game-btn {
  background: #8f7a66;
  color: white;
  border: none;
  padding: 15px 30px;
  border-radius: 10px;
  font-size: 18px;
  cursor: pointer;
  transition: background 0.3s;
}

.new-game-btn:hover {
  background: #7f6a56;
}

.game-board {
  background: #bbada0;
  border-radius: 10px;
  padding: 15px;
  margin-bottom: 20px;
  outline: none;
}

.grid-container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 15px;
  background: #bbada0;
}

.grid-row {
  display: contents;
}

.grid-cell {
  width: 100%;
  height: 80px;
  background: #cdc1b4;
  border-radius: 8px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 32px;
  font-weight: bold;
  color: #776e65;
  transition: all 0.15s ease;
}

.grid-cell.empty {
  background: #cdc1b4;
}

.tile-2 { background: #eee4da; }
.tile-4 { background: #ede0c8; }
.tile-8 { background: #f2b179; color: white; }
.tile-16 { background: #f59563; color: white; }
.tile-32 { background: #f67c5f; color: white; }
.tile-64 { background: #f65e3b; color: white; }
.tile-128 { background: #edcf72; color: white; font-size: 28px; }
.tile-256 { background: #edcc61; color: white; font-size: 28px; }
.tile-512 { background: #edc850; color: white; font-size: 28px; }
.tile-1024 { background: #edc53f; color: white; font-size: 24px; }
.tile-2048 { background: #edc22e; color: white; font-size: 24px; }

.game-over, .win {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.game-over-content, .win-content {
  background: white;
  padding: 40px;
  border-radius: 20px;
  text-align: center;
  max-width: 400px;
}

.game-over-content h2, .win-content h2 {
  color: #776e65;
  margin-bottom: 20px;
  font-size: 32px;
}

.game-over-content p, .win-content p {
  color: #776e65;
  margin-bottom: 30px;
  font-size: 18px;
}

.continue-btn {
  background: #8f7a66;
  color: white;
  border: none;
  padding: 15px 30px;
  border-radius: 10px;
  font-size: 18px;
  cursor: pointer;
  margin-right: 10px;
  transition: background 0.3s;
}

.continue-btn:hover {
  background: #7f6a56;
}

@media (max-width: 600px) {
  .game-container {
    padding: 20px;
  }
  
  .header h1 {
    font-size: 36px;
  }
  
  .grid-cell {
    height: 60px;
    font-size: 24px;
  }
  
  .score-container {
    flex-direction: column;
    align-items: center;
    gap: 10px;
  }
}
</style>
